package com.itboye.api.controller;

import com.itboye.api.interfaces.IDomainParams;
import com.itboye.api.model.ByRequestData;
import com.itboye.config.GlobalConfig;
import com.itboye.mybatis.model.OAuthClients;
import com.itboye.mybatis.model.UcenterAppModel;
import com.itboye.services.ucenter.impl.UcenterAppService;
import com.itboye.services.utils.impl.OAuthClientsService;
import com.itboye.services.utils.interfaces.IOAuthClientsService;
import com.itboye.system.crypt.DesCrypt;
import com.itboye.system.crypt.JsonCrypt;
import com.itboye.system.exception.ByBaseException;
import com.itboye.system.exception.ByExceptionCode;
import com.itboye.system.helper.ByConfigHelper;
import com.itboye.system.helper.ByConsoleHelper;
import com.itboye.api.model.ByResponseData;

import com.itboye.system.helper.ByDateHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;

/**
 * 接口网关
 * Created by hebidu on 16/5/7.
 */
@Controller
public class IndexController {

//    private ByRequestData requestData;
    private ThreadLocal<ByRequestData> localRequestData = new ThreadLocal<ByRequestData>();

    public ByRequestData getLocalRequestData() {
        return localRequestData.get();
    }

    public void setLocalRequestData(ByRequestData requestData) {
        localRequestData.set(requestData);
    }

    private static final Logger logger = LogManager.getLogger(IndexController.class.toString());

    @Resource
    private IOAuthClientsService oAuthClientsService;

    /**
     * 更新日志记录
     * @return
     * @throws IOException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws ByBaseException
     * @throws NoSuchAlgorithmException
     */
    @RequestMapping(value = "/version",produces = "text/html;charset=UTF-8")
    public ModelAndView version() throws IOException, IllegalAccessException, InstantiationException, ByBaseException, NoSuchAlgorithmException {

        HashMap<String,String> userdata = new HashMap<String, String>();

        userdata.put("version", ByConfigHelper.getInstance().read("app_version"));

        return new ModelAndView("version",userdata);
    }


    @RequestMapping(value = "/timestamp",produces = "text/html;charset=UTF-8")
    public ModelAndView timestamp() throws IOException, IllegalAccessException, InstantiationException, ByBaseException, NoSuchAlgorithmException {

        HashMap<String,String> userdata = new HashMap<String, String>();

        userdata.put("datetime", ByDateHelper.getDefaultDateFormatStr());


        return new ModelAndView("timestamp",userdata);
    }

    @RequestMapping(value = "/gateway",produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String index() throws IOException, IllegalAccessException, InstantiationException, ByBaseException, NoSuchAlgorithmException {


        ByConsoleHelper.debug("进入接口入口",logger);
        //1. 获取必要参数
        this.initFromRequest();
        ByConsoleHelper.debug("初始化参数从请求中",logger);
        //2. 必要参数验证
        getLocalRequestData().isValid();
        ByConsoleHelper.debug("参数已通过验证",logger);
        //3. 获取业务参数
        HashMap params =  getLocalRequestData().getParams();
        ByConsoleHelper.debug("参数解密后:"+params.toString(),logger);

        //4. 调用服务
        //包名
        String packageNS = "com.itboye.api.domain.";
        String type = getLocalRequestData().getType();

        String[] splitType =  type.split("_",3);

        if(splitType.length != 3){
            throw new ByBaseException("请求接口类型参数无效!");
        }


        String domainClass = splitType[1]+"Domain";
        String methodName = splitType[2];


        try {

            ApplicationContext act = ContextLoader.getCurrentWebApplicationContext();

            ByConsoleHelper.debug("调用类与方法="+packageNS+domainClass+"-"+methodName,logger);
            Class<?> cls =   Class.forName(packageNS+domainClass);
            Method method = cls.getMethod(methodName);
            Object instance = act.getBean(domainClass);
            IDomainParams domainParams = (IDomainParams) instance;

            if(domainParams == null){
                throw new ByBaseException("调用服务非法");
            }

            domainParams.initAllNeedParams(params,getLocalRequestData());

            ByResponseData resp = (ByResponseData)method.invoke(instance);

            if(resp == null){
                ByConsoleHelper.info("返回为null",logger);
            }else{
                ByConsoleHelper.info("返回信息:"+resp.toJson(),logger);
                return  resp.toJson();
            }

        } catch (ClassNotFoundException e) {
            ByConsoleHelper.info("请求服务不存在",logger);
        }
        catch (NoSuchMethodException e) {
            ByConsoleHelper.info("请求服务的方法不存在",logger);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            ByConsoleHelper.info("调用目标出错:" + e.getMessage(),logger);
            if(e.getCause() != null){
                ByConsoleHelper.info("调用目标出错:" + e.getCause().getMessage(),logger);
            }
            if(e.getTargetException() instanceof ByBaseException){
               return error(((ByBaseException) e.getTargetException()).getCode(),e.getTargetException().getMessage());
            }
        }catch (ByBaseException e){
            ByConsoleHelper.info("调用发生错误" + e.getMessage(),logger);
        }

        return error(ByExceptionCode.Business_Error,"服务器开小差了");
    }

    private String error(String code,String msg) throws NoSuchAlgorithmException{
        try {
            return  ByResponseData.fail(code,msg, GlobalConfig.DEFAULT_CLIENT_SECRET,GlobalConfig.DEFAULT_NOTIFY_ID).toJson();
        } catch (UnsupportedEncodingException e) {
            ByConsoleHelper.info(e.getLocalizedMessage(),logger);
        } catch (ByBaseException e) {
            ByConsoleHelper.info(e.getLocalizedMessage(),logger);
        }

        return "";
    }


    /**
     * 从RequestContextHolder获取
     * @return HttpServletRequest
     */
    private HttpServletRequest getRequest(){
        return ((ServletRequestAttributes)(RequestContextHolder.currentRequestAttributes())).getRequest();
    }

    /**
     * 从请求中获取所需参数
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     * @throws ByBaseException
     */
    private void initFromRequest() throws UnsupportedEncodingException, NoSuchAlgorithmException, ByBaseException {

        ByConsoleHelper.debug("当前线程"+Thread.currentThread().getId(),logger);


        HttpServletRequest request = getRequest();
        if(request == null){
            throw  new ByBaseException("Request 为空");
        }
        String clientId = request.getParameter("client_id");
        if(clientId == null || clientId.length() == 0){
            throw  new ByBaseException("clientId参数缺失");
        }

        String itboye = request.getParameter("itboye");
        String clientSecret = getClientSecret(clientId);

        ByConsoleHelper.debug("client_id= "+clientId,logger);
        ByConsoleHelper.debug("加密后的数据itboye= "+itboye,logger);
        ByConsoleHelper.debug("秘钥 "+clientSecret,logger);
//        itboye = Base64Crypt.decode(itboye);
        ByConsoleHelper.debug("itboyebase64解密后= "+itboye,logger);

        String decodeData = DesCrypt.decode(itboye,clientSecret);

        if(decodeData == null){
            throw  new ByBaseException(clientSecret+"请求参数解析失败"+itboye);
        }

        setLocalRequestData(JsonCrypt.readValue(decodeData,ByRequestData.class));
        if(getLocalRequestData() == null){
            throw  new ByBaseException("请求参数解析结果为null");
        }else {

            //设置clientId和秘钥
            getLocalRequestData().setClientId(clientId);
            getLocalRequestData().setClientSecret(clientSecret);

            ByConsoleHelper.debug("请求参数解析结果"+getLocalRequestData().toString(),logger);

        }
    }


    /**
     * 获取秘钥
     * @param clientId
     * @return
     */
    private String getClientSecret(String clientId) throws ByBaseException {

        HashMap<String,String> params = new HashMap<String, String>();
        params.put("clientId",clientId);

        OAuthClients model = oAuthClientsService.getInfoBy(params);

        if(model == null){
            throw  new ByBaseException("参数app_id无效");
        }
        ByConsoleHelper.debug("获取到的秘钥"+model.toString(),logger);
        return model.getClientSecret();
    }

}
